#pragma once

#include <linux/bit_spinlock.h>

#define LIST_BL_LOCKMASK 0

struct hlist_bl_head
{
    struct hlist_bl_node *first;
};

struct hlist_bl_node
{
    struct hlist_bl_node *next, **pprev;
};

#define hlist_bl_entry(ptr, type, member) container_of(ptr, type, member)

static inline void INIT_HLIST_BL_NODE(struct hlist_bl_node *h)
{
    h->next = NULL;
    h->pprev = NULL;
}

static inline bool hlist_bl_is_locked(struct hlist_bl_head *b)
{
    return bit_spin_is_locked(0, (unsigned long *)b);
}

static inline void hlist_bl_lock(struct hlist_bl_head *b)
{
    pr_todo();
}

static inline void hlist_bl_unlock(struct hlist_bl_head *b)
{
}

static inline struct hlist_bl_node *hlist_bl_first(struct hlist_bl_head *h)
{
    return (struct hlist_bl_node *)((uintptr_t)h->first & ~LIST_BL_LOCKMASK);
}

static inline bool hlist_bl_unhashed(const struct hlist_bl_node *h)
{
    return !h->pprev;
}

/**
 * hlist_bl_for_each_entry	- iterate over list of given type
 * @tpos:	the type * to use as a loop cursor.
 * @pos:	the &struct hlist_node to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the hlist_node within the struct.
 *
 */
#define hlist_bl_for_each_entry(tpos, pos, head, member) \
    for (pos = hlist_bl_first(head);                     \
         pos &&                                          \
         ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; });                                          \
         pos = pos->next)
